﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

//import com.mojang.mario.Art;
//import com.mojang.mario.LevelScene;

using JavaSubstitutes;


namespace Sprites
{
	public class Enemy: Sprite
	{
		public const int ENEMY_RED_KOOPA = 0;
		public const int ENEMY_GREEN_KOOPA = 1;
		public const int ENEMY_GOOMBA = 2;
		public const int ENEMY_SPIKY = 3;
		public const int ENEMY_FLOWER = 4;

		private static double GROUND_INERTIA = 0.89f;
		private static double AIR_INERTIA = 0.89f;

		private double runTime;
		private bool onGround = false;
		private bool mayJump = false;
		//private int jumpTime = 0;
		//private double xJumpSpeed;
		//private double yJumpSpeed;

		public int width = 4;
		public int height = 24;

		private LevelScene world;
		public int facing;
		public int deadTime = 0;
		public bool flyDeath = false;

		public bool avoidCliffs = true;
		private int type;

		public bool winged = true;
		private int wingTime = 0;

		public bool noFireballDeath;

		public Enemy(LevelScene world, int x, int y, int dir, int type, bool winged)
		{
			this.type = type;
			sheet = Art.enemies;
			this.winged = winged;

			this.x = x;
			this.y = y;
			this.world = world;
			xPicO = 8;
			yPicO = 31;

			avoidCliffs = type == Enemy.ENEMY_RED_KOOPA;

			noFireballDeath = type == Enemy.ENEMY_SPIKY;

			yPic = type;
			if (yPic > 1) height = 12;
			facing = dir;
			if (facing == 0) facing = 1;
			this.wPic = 16;
		}

		public override void collideCheck()
		{
			if (deadTime != 0)
			{
				return;
			}

			double xMarioD = world.mario.x - x;
			double yMarioD = world.mario.y - y;
			//double w = 16;
			if (xMarioD > -width * 2 - 4 && xMarioD < width * 2 + 4)
			{
				if (yMarioD > -height && yMarioD < world.mario.height)
				{
					if (type != Enemy.ENEMY_SPIKY && world.mario.yDelta > 0 && yMarioD <= 0 && (!world.mario.onGround || !world.mario.wasOnGround))
					{
						world.mario.stomp(this);
						if (winged)
						{
							winged = false;
							yDelta = 0;
						}
						else
						{
							this.yPicO = 31 - (32 - 8);
							hPic = 8;
							if (spriteTemplate != null) spriteTemplate.isDead = true;
							deadTime = 10;
							winged = false;

							if (type == Enemy.ENEMY_RED_KOOPA)
							{
								spriteContext.addSprite(new Shell(world, x, y, 0));
							}
							else if (type == Enemy.ENEMY_GREEN_KOOPA)
							{
								spriteContext.addSprite(new Shell(world, x, y, 1));
							}
						}
					}
					else
					{
						world.mario.getHurt();
					}
				}
			}
		}

		public override void move()
		{
			wingTime++;
			if (deadTime > 0)
			{
				deadTime--;

				if (deadTime == 0)
				{
					deadTime = 1;
					for (int i = 0; i < 8; i++)
					{
						world.addSprite(new Sparkle((int)(x + RandomExtensions.random() * 16 - 8) + 4, (int)(y - RandomExtensions.random() * 8) + 4, (double)(RandomExtensions.random() * 2 - 1), (double)RandomExtensions.random() * -1, 0, 1, 5));
					}
					spriteContext.removeSprite(this);
				}

				if (flyDeath)
				{
					x += xDelta;
					y += yDelta;
					yDelta *= 0.95f;
					yDelta += 1;
				}
				return;
			}


			double sideWaysSpeed = 1.75f;
			//        double sideWaysSpeed = onGround ? 2.5f : 1.2f;

			if (xDelta > 2)
			{
				facing = 1;
			}
			if (xDelta < -2)
			{
				facing = -1;
			}

			xDelta = facing * sideWaysSpeed;

			mayJump = (onGround);

			xFlipPic = facing == -1;

			runTime += (Math.Abs(xDelta)) + 5;

			int runFrame = ((int)(runTime / 20)) % 2;

			if (!onGround)
			{
				runFrame = 1;
			}


			if (!move(xDelta, 0)) facing = -facing;
			onGround = false;
			move(0, yDelta);

			yDelta *= winged ? 0.95f : 0.85f;
			if (onGround)
			{
				xDelta *= GROUND_INERTIA;
			}
			else
			{
				xDelta *= AIR_INERTIA;
			}

			if (!onGround)
			{
				if (winged)
				{
					yDelta += 0.6f;
				}
				else
				{
					yDelta += 2;
				}
			}
			else if (winged)
			{
				yDelta = -10;
			}

			if (winged) runFrame = wingTime / 4 % 2;

			xPic = runFrame;
		}

		private bool move(double xa, double ya)
		{
			while (xa > 8)
			{
				if (!move(8, 0)) return false;
				xa -= 8;
			}
			while (xa < -8)
			{
				if (!move(-8, 0)) return false;
				xa += 8;
			}
			while (ya > 8)
			{
				if (!move(0, 8)) return false;
				ya -= 8;
			}
			while (ya < -8)
			{
				if (!move(0, -8)) return false;
				ya += 8;
			}

			bool collide = false;
			if (ya > 0)
			{
				if (isBlocking(x + xa - width, y + ya, xa, 0)) collide = true;
				else if (isBlocking(x + xa + width, y + ya, xa, 0)) collide = true;
				else if (isBlocking(x + xa - width, y + ya + 1, xa, ya)) collide = true;
				else if (isBlocking(x + xa + width, y + ya + 1, xa, ya)) collide = true;
			}
			if (ya < 0)
			{
				if (isBlocking(x + xa, y + ya - height, xa, ya)) collide = true;
				else if (collide || isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
				else if (collide || isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
			}
			if (xa > 0)
			{
				if (isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
				if (isBlocking(x + xa + width, y + ya - height / 2, xa, ya)) collide = true;
				if (isBlocking(x + xa + width, y + ya, xa, ya)) collide = true;

				if (avoidCliffs && onGround && !world.level.isBlocking((int)((x + xa + width) / 16), (int)((y) / 16 + 1), xa, 1)) collide = true;
			}
			if (xa < 0)
			{
				if (isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
				if (isBlocking(x + xa - width, y + ya - height / 2, xa, ya)) collide = true;
				if (isBlocking(x + xa - width, y + ya, xa, ya)) collide = true;

				if (avoidCliffs && onGround && !world.level.isBlocking((int)((x + xa - width) / 16), (int)((y) / 16 + 1), xa, 1)) collide = true;
			}

			if (collide)
			{
				if (xa < 0)
				{
					x = (int)((x - width) / 16) * 16 + width;
					this.xDelta = 0;
				}
				if (xa > 0)
				{
					x = (int)((x + width) / 16 + 1) * 16 - width - 1;
					this.xDelta = 0;
				}
				if (ya < 0)
				{
					y = (int)((y - height) / 16) * 16 + height;
					//jumpTime = 0;
					this.yDelta = 0;
				}
				if (ya > 0)
				{
					y = (int)(y / 16 + 1) * 16 - 1;
					onGround = true;
				}
				return false;
			}
			else
			{
				x += xa;
				y += ya;
				return true;
			}
		}

		private bool isBlocking(double _x, double _y, double xa, double ya)
		{
			int x = (int)(_x / 16);
			int y = (int)(_y / 16);
			if (x == (int)(this.x / 16) && y == (int)(this.y / 16)) return false;

			bool blocking = world.level.isBlocking(x, y, xa, ya);

			byte block = world.level.getBlock(x, y);

			return blocking;
		}

		public override bool shellCollideCheck(Shell shell)
		{
			if (deadTime != 0) return false;

			double xD = shell.x - x;
			double yD = shell.y - y;

			if (xD > -16 && xD < 16)
			{
				if (yD > -height && yD < shell.height)
				{
					world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);

					xDelta = shell.facing * 2;
					yDelta = -5;
					flyDeath = true;
					if (spriteTemplate != null) spriteTemplate.isDead = true;
					deadTime = 100;
					winged = false;
					hPic = -hPic;
					yPicO = -yPicO + 16;
					return true;
				}
			}
			return false;
		}

		public override bool fireballCollideCheck(Fireball fireball)
		{
			if (deadTime != 0) return false;

			double xD = fireball.x - x;
			double yD = fireball.y - y;

			if (xD > -16 && xD < 16)
			{
				if (yD > -height && yD < fireball.height)
				{
					if (noFireballDeath) return true;

					world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);

					xDelta = fireball.facing * 2;
					yDelta = -5;
					flyDeath = true;
					if (spriteTemplate != null) spriteTemplate.isDead = true;
					deadTime = 100;
					winged = false;
					hPic = -hPic;
					yPicO = -yPicO + 16;
					return true;
				}
			}
			return false;
		}

		public override void bumpCheck(int xTile, int yTile)
		{
			if (deadTime != 0) return;

			if (x + width > xTile * 16 && x - width < xTile * 16 + 16 && yTile == (int)((y - 1) / 16))
			{
				world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);

				xDelta = -world.mario.facing * 2;
				yDelta = -5;
				flyDeath = true;
				if (spriteTemplate != null) spriteTemplate.isDead = true;
				deadTime = 100;
				winged = false;
				hPic = -hPic;
				yPicO = -yPicO + 16;
			}
		}

		//public void render(Graphics og, double alpha)
		public override void render(WriteableBitmap wbmp, double alpha)
		{
			if (winged)
			{
				int xPixel = (int)(xOld + (x - xOld) * alpha) - xPicO;
				int yPixel = (int)(yOld + (y - yOld) * alpha) - yPicO;

				if (type == Enemy.ENEMY_GREEN_KOOPA || type == Enemy.ENEMY_RED_KOOPA)
				{
				}
				else
				{
					xFlipPic = !xFlipPic;
					wbmp.drawImage(sheet[wingTime / 4 % 2,4], xPixel + (xFlipPic ? wPic : 0) + (xFlipPic ? 10 : -10), yPixel + (yFlipPic ? hPic : 0) - 8, xFlipPic ? -wPic : wPic, yFlipPic ? -hPic : hPic);
					xFlipPic = !xFlipPic;
				}
			}

			base.render(wbmp, alpha);

			if (winged)
			{
				int xPixel = (int)(xOld + (x - xOld) * alpha) - xPicO;
				int yPixel = (int)(yOld + (y - yOld) * alpha) - yPicO;

				if (type == Enemy.ENEMY_GREEN_KOOPA || type == Enemy.ENEMY_RED_KOOPA)
				{
					wbmp.drawImage(sheet[wingTime / 4 % 2,4], xPixel + (xFlipPic ? wPic : 0) + (xFlipPic ? 10 : -10), yPixel + (yFlipPic ? hPic : 0) - 10, xFlipPic ? -wPic : wPic, yFlipPic ? -hPic : hPic);
				}
				else
				{
					wbmp.drawImage(sheet[wingTime / 4 % 2,4], xPixel + (xFlipPic ? wPic : 0) + (xFlipPic ? 10 : -10), yPixel + (yFlipPic ? hPic : 0) - 8, xFlipPic ? -wPic : wPic, yFlipPic ? -hPic : hPic);
				}
			}
		}
	}
}